/* Alloc for fixed size blocks and for aligned storage       Jack Snoeyink 
 * FixedAlloc.h
 */

#include <stdio.h>
#include <stdlib.h>

#ifndef NULL
#define NULL 0
#endif

void fatalError(msg, var)
     char *msg, *var;
{
  fprintf(stderr, msg, var);
  fflush(stderr);
  exit(1);
}


void *_FA_new(freelist)	/* WARNING: freelist is modified! */
     void **freelist;
{
  void *tmp;

  if (*freelist == NULL)
    fatalError("Used up all storage blocks%s\n", " ");
  tmp = *freelist;
  *freelist = *((void **) tmp);
  return (tmp);
}

void *_FA_dispose(ptr, freelist) /* WARNING: freelist modified! */
void **ptr, **freelist;
{
  *ptr = *freelist;
  *freelist = ptr;
}


void *FA_Alloc(size, max, name)
     int size, max;
     char *name;
{
  void **ptr, *last;
  int i;
  
  if ((ptr = (void **) malloc(max * size)) == NULL) 
    fatalError("Malloc: error allocating %s\n", name);
  last = NULL;
  for (i = 0; i < max; i++)
    { 
      *ptr = last; 
      last = (void *) ptr; 
      ptr = (void *) ((unsigned int) ptr + size); 
    }
  return ((void *) last);
}


void *FA_Aligned_Alloc(size, max, name)
     int size, max;
     char *name;
{
  void  **ptr, *last;
  int size2, i;
  
  for (size2 = 1; size2 < size; size2 <<= 1);
  if (size != size2)
    fatalError("Size %d must be a power of two\n", size);
  
  if ((ptr = (void **) malloc((max+1) * size)) == NULL) 
    fatalError("Malloc: error allocating %s\n", name);

  ptr = (void **)(((unsigned int) ptr | (size - 1)) + 1); /* Align */

  last = NULL;
  for (i = 0; i < max; i++)
    { 
      *ptr = last; 
      last = (void *) ptr; 
      ptr = (void *)((unsigned int) ptr + size); 
    }
  return ((void *) last);
}





